package cn.sangedon.review.analysis.stastics.specific;

import cn.sangedon.review.analysis.service.TrendStasticsService;
import cn.sangedon.review.analysis.stastics.IStastics;
import cn.sangedon.review.common.constant.TypeConstant;
import cn.sangedon.review.common.domain.analysis.TrendStastics;
import cn.sangedon.review.common.domain.data.StockDayInfo;
import cn.sangedon.review.common.service.data.StockDayInfoService;
import cn.sangedon.review.common.service.data.TradingDateService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

@Slf4j
@Component
public class MarketTrendStastics implements IStastics {
    @DubboReference
    private StockDayInfoService stockDayInfoService;

    @DubboReference
    private TradingDateService tradingDateService;

    @Autowired
    private TrendStasticsService trendStasticsService;

    @Override
    public void stastic() {
        trendStastics(stockDayInfoService.getLatestDate(), 4);
    }

    /**
     * 统计每只股票对比前多少个交易日的股票涨跌情况
     *
     * @param tradeDay 参照的交易日
     * @param tradeDateAgo 参照的交易日之前的多少个交易日数据
     * @return
     */
    public List<TrendStastics> trendStastics(String tradeDay, Integer tradeDateAgo) {
        QueryWrapper<TrendStastics> query = new QueryWrapper<>();
        query.eq("trade_date", tradeDay);
        query.eq("cycle", tradeDateAgo + 1);
        long count = trendStasticsService.count(query);
        if (count > 0) {
            return trendStasticsService.list(query);
        }
        return trendStastics(tradeDay, tradingDateService.getTradeDateAgo(tradeDay, tradeDateAgo));
    }

    /**
     * 统计每只股票对比某个日期行情的情况
     *
     * @param tradeDay 交易日
     * @param compareTradeday 对比的交易日
     * @return
     */
    public List<TrendStastics> trendStastics(String tradeDay, String compareTradeday) {
        if (StringUtils.isEmpty(tradeDay) || StringUtils.isEmpty(compareTradeday)) {
            log.info("股票统计数据为空或者对比日期为空，是否对比日期为空：{}", StringUtils.isEmpty(compareTradeday));
            return Collections.emptyList();
        }
        log.info("开始计算{} ~ {}之间股票的价格变化", compareTradeday, tradeDay);
        List<StockDayInfo> latestStockInfos = stockDayInfoService.getStockDayInfos(tradeDay, TypeConstant.EQ);
        List<StockDayInfo> compareStockInfos = stockDayInfoService.getStockDayInfos(compareTradeday, TypeConstant.EQ);
        List<TrendStastics> trendStastics = trendStastics(latestStockInfos, compareStockInfos);
        log.info("计算{} ~ {}之间股票的价格变化结束", compareTradeday, tradeDay);
        return trendStastics;
    }

    private List<TrendStastics> trendStastics(List<StockDayInfo> latestStockInfos, List<StockDayInfo> compareStockInfos) {

        List<TrendStastics> trends = new ArrayList<>();
        Map<String, StockDayInfo> compareStockInfoMap = compareStockInfos.stream().collect(
            Collectors.toMap(StockDayInfo::getCode, Function.identity()));

        latestStockInfos.forEach(e -> {
            StockDayInfo compareStockInfo = compareStockInfoMap.get(e.getCode());
            if (compareStockInfo == null) {
                return;
            }

            TrendStastics trendStastics = new TrendStastics();
            trendStastics.setStockCode(e.getCode());
            trendStastics.setStockName(e.getName());
            trendStastics.setTradeDate(e.getTradingDate());
            double changeRate = e.getClosingPrice().subtract(compareStockInfo.getClosingPrice()).multiply(new BigDecimal(100))
                                 .divide(compareStockInfo.getClosingPrice(), 4, RoundingMode.HALF_DOWN).doubleValue();
            trendStastics.setChangeRate(changeRate);
            Integer distance = tradingDateService.distance(e.getTradingDate(), compareStockInfo.getTradingDate());
            trendStastics.setCycle(distance);
            trends.add(trendStastics);
        });

        trendStasticsService.saveBatch(trends);
        return trends;
    }
}
